// /////////////////////////////////////////////////////////////////////////////
//
// Name:            AssetManager.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           The AssetManager class manages the AssetGroups that are being
//                  used by the framework.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "AssetManager.h"


// AssetManager class
// AssetManager constructor.
AssetManager::AssetManager()
{
}

// AssetManager deconstructor.
AssetManager::~AssetManager()
{
}

// Initialises the AssetManager.
void AssetManager::init()
{
    registerProcessorFactories();
}

// Clears the AssetManager.
void AssetManager::clear()
{
    removeAssetGroups();
}

// Increases the reference counter.
void AssetManager::grab()
{
    // Dummy function.
}

// Decreases the reference counter.
void AssetManager::drop()
{
    // Dummy function.
}

// Adds the given AssetGroup to the AssetManager.
bool AssetManager::addAssetGroup(AssetGroup *group)
{
    // Did we get a valid pointer?
    if(group == NULL)
      return false;

    // Does a AssetGroup with the same name exist?
    if(getAssetGroup(group->getName()))
      return false;

    // Add the AssetGroup to the vector.
    mGroups.push_back(group);
    group->grab();

    return true;
}

// Creates (and adds) a AssetGroup with the given name.
AssetGroup* AssetManager::createAssetGroup(const std::string &name, const std::string &dirName, bool grab)
{
    // Does a Data group with the same name exist?
    if(grab && getAssetGroup(name))
      return NULL;

    // Create the AssetGroup and add it to the vector.
    AssetGroup *group = new AssetGroup(name, dirName);

    if(grab)
    {
       mGroups.push_back(group);
       group->grab();
    }

    return group;
}

// Gets the AssetGroup with the given ID.
AssetGroup* AssetManager::getAssetGroup(const u32 id)
{
    for(u32 i = 0; i < mGroups.size(); i++)
    {
       if(mGroups[i]->getID() == id)
         return mGroups[i];
    }

    return NULL;
}

// Gets the AssetGroup with the given name.
AssetGroup* AssetManager::getAssetGroup(const std::string &name)
{
    for(u32 i = 0; i < mGroups.size(); i++)
    {
       if(mGroups[i]->getName() == name)
         return mGroups[i];
    }

    return NULL;
}

// Stores new instances of asset processors in the given vector.
void AssetManager::getAssetProcessors(AssetGroup *group,
                                      std::vector<AssetProcessor*> &assetProcessors)
{
    std::map<std::string, AssetProcessor* (*)(AssetGroup*)>::iterator it;

    for(it = mProcessorFactories.begin(); it != mProcessorFactories.end(); it++)
      assetProcessors.push_back( (*(it->second))(group) );
}

// Registers a factory function for a AssetProcessor.
bool AssetManager::registerProcessorFactory(const std::string &name,
                                            AssetProcessor* (*f)(AssetGroup*))
{
    // Does a processor factory with the same name exist?
    std::map<std::string, AssetProcessor* (*)(AssetGroup*)>::iterator it;
    it = mProcessorFactories.find(name);

    if(it != mProcessorFactories.end())
      return false;

    // Add the processor factory  to the map.
    mProcessorFactories[name] = f;
    return true;
}

// Unregisters a factory function for a AssetProcessor.
bool AssetManager::unregisterProcessorFactory(const std::string &name)
{
    // Try to remove the processor factory.
    std::map<std::string, AssetProcessor* (*)(AssetGroup*)>::iterator it;
    it = mProcessorFactories.find(name);

    if(it != mProcessorFactories.end())
    {
       mProcessorFactories.erase(it);
       return true;
    }

    // We couldn't find the factory and thus couldn't remove it.
    return false;
}

// Unregisters all AssetProcessor factory functions.
void AssetManager::unregisterProcessorFactories()
{
    mProcessorFactories.clear();
}

// Removes all AssetGroups from this AssetManager.
void AssetManager::removeAssetGroups()
{
    // Clear the AssetGroups.
    for(u32 i = 0; i < mGroups.size(); i++)
       mGroups[i]->drop();

    mGroups.clear();
}

// Removes the given AssetGroup.
bool AssetManager::removeAssetGroup(AssetGroup *group)
{
    // Did we get a valid pointer?
    if(group == NULL)
      return false;

    // Try to remove the AssetGroup.
    vector<AssetGroup*>::iterator it;

    for(it = mGroups.begin(); it < mGroups.end(); it++)
    {
        AssetGroup *agroup = *it;

        if(agroup == group)
        {
           agroup->drop();
           mGroups.erase(it);
           return true;
        }
    }

    // We couldn't find the AssetGroup and thus couldn't remove it.
    return false;
}

// Removes the given AssetGroup with the given ID.
bool AssetManager::removeAssetGroup(const u32 id)
{
    // Try to remove the AssetGroup.
    vector<AssetGroup*>::iterator it;

    for(it = mGroups.begin(); it < mGroups.end(); it++)
    {
        AssetGroup *agroup = *it;

        if(agroup->getID() == id)
        {
           agroup->drop();
           mGroups.erase(it);
           return true;
        }
    }

    // We couldn't find the AssetGroup and thus couldn't remove it.
    return false;
}

// Removes the given AssetGroup with the given name.
bool AssetManager::removeAssetGroup(const std::string &name)
{
    // Try to remove the AssetGroup.
    vector<AssetGroup*>::iterator it;

    for(it = mGroups.begin(); it < mGroups.end(); it++)
    {
        AssetGroup *agroup = *it;

        if(agroup->getName() == name)
        {
           agroup->drop();
           mGroups.erase(it);
           return true;
        }
    }

    // We couldn't find the AssetGroup and thus couldn't remove it.
    return false;
}

// End of File
